package com.winner.data.util;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/**
 * 带 Z 的是utc时间 还是 带T是utc时间?
 * ‌带Z的时间表示UTC时间‌。在ISO 8601标准中，时间格式“2021-08-25T10:15:30Z”表示的是UTC时间的2021年8月25日10点15分30秒。
 * 其中，“T”表示日期和时间的分隔符，“Z”表示UTC时区的标识‌(Z代表的是zero，零时区，也就是UTC时间)
 * 1.当我们看到：2021-08-25T10:15:30Z , 就是UTC时间
 * 2.当我们看到：2022-09-19T06:22:34+00:00 ,其中00:00代表的也是零时区,也就是UTC时间
 * 3.当我们看到：2022-09-19T14:22:34+08:00 ,其中00:00代表的也是东八区
 *
 * JAVA8的时区转换
 * UTC时间, 协调世界时，又称世界统一时间、世界标准时间、国际协调时间。 全球一共分为24个时区，规定英国的格林威治地区为0时区,每个相邻时区时间相差一个小时, 中国就是东八区时间
 * 0时区时间指格林威治时间1970年01月01日00时00分00秒 也就是北京时间的 1970-01-01 08:00:00, 此刻的毫秒值为 0L
 * 如果只有一个站点的话(一般不会), 全球不同国家都访问, 只能靠浏览器和操作系统的时区, 前端传参给后端, 后端转为相应时区的时间后返回给前端
 * "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"    Z表示UTC时间的标记, 而T并不能表示UTC时间
 *
 * 操作系统时区 JVM时区和浏览器时区(都由操作系统时区决定) 数据库时区
 * 数据库安装时区的设置: MYSQL默认使用系统时区,查询当前时区 show variables like '%time_zone%'; 安装数据库的时候，选择时区，依然选择中国区(站点对应的国家区)
 * Mysql时间字段用datetime类型,代码统一转为UTC时间入库, 比较大小的时候直接用 b.create_time < UTC_TIMESTAMP() 即可.
 * SELECT UTC_TIMESTAMP(); 比 SELECT CURRENT_TIMESTAM;少8小时
 *
 * @author wangxinle5
 * @since 2022-12-23
 */
public class UtcDateUtil {

    public static void main(String[] args) {

        // 从数据库中获取的UTC时间, 即 Instant 来接收数据库的utc时间字段
        Instant utcTime = Instant.parse("2022-09-26T09:00:00.00Z");
        System.out.println("数据库的UTC时间转为北京时间(即 北京时间 = 数据库的UTC时间+8小时), 结果是: " + utcToLocal(utcTime));

        // 创建北京时间 2023-09-26 09:00:00, 调用.toInstant(), 即转为了utc时间
        Instant instant = DateUtil.parse("2023-09-26 09:00:00").toInstant();
        System.out.println("北京时间转为UTC时间(即 UTC时间 = 北京时间-8小时), 结果是 " + instant);

        Instant fromDb = Instant.now();
        System.out.println("拿到当前服务器所在时区对应的UTC时间是:" + fromDb);
    }


    /**
     * 数据库的utc时间转为北京时间, 这样前端就可以直接用
     *
     * @param utcTime 即数据库存的就是utc时间, java实体类用Instant接收utc时间
     * @return String
     */
    public static String utcToLocal(Instant utcTime) {
        // 定义服务器所在的时区  例如北京时区 ZoneId beijingZone = ZoneId.of("Asia/Shanghai");
        ZoneId beijingZone = ZoneId.systemDefault();
        ZonedDateTime zonedDateTime = utcTime.atZone(beijingZone);
        // 格式化  如果不格式化, 直接返回zonedDateTime前端收到的就是2022-09-26T17:30:00+08:00
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN);
        return zonedDateTime.format(dateTimeFormatter);
    }


    /**
     * 前端传过来的北京时间转为utc时间 入库
     * toInstant()方法, 即将北京时间转为UTC时间(比当前时间少了8小时)  北京时间（中国标准时间，CST）通常是UTC+8。UTC时间 = 北京时间 - 8小时
     *
     * @param dateTime 前端传过来的北京时间
     * @return Instant
     */
    public static Instant localToUtc(Date dateTime) {
        return dateTime.toInstant();
    }

}
